/**
 * Created by woziji00226 on 2022-09-27 09:30:19.
 * FXF YES!
 */

class W26_CzMagazineBullet extends GUI_15003 {
    /**
     * 构造函数
     */
    constructor(use: string, full: string) {
        super();
        this.fullBullet();
        this.use.image = use;
        this.full.image = full;
    }

    useBullet() {
        this.full.visible = false;
        this.use.visible = true;
    }

    fullBullet() {
        this.full.visible = true;
        this.use.visible = false;
    }
}

class W26_CzBullet extends GUI_15002 {
    static STATE_READY = 0;//准备
    static STATE_FIRE = 1;
    static STATE_INSERT = 2;
    static STATE_DROP = 3;
    static STATE_DOUNCE = 4;
    depth: number;
    state: number;//状态
    circleParent: W26_CzCircle;
    speed: number;
    vSpeed: number;//水平速度
    aSpeed: number;//角度力
    angle: number;//插入角度

    currentSpeed: number;//当前速度

    g: number;//重力
    v: number;//水平推力
    /**
     * 构造函数
     */
    constructor(img: string) {
        super();
        this.depth = 20;
        this.speed = -100;
        this.g = 90;

        this.state = W26_CzBullet.STATE_READY;
        this.speed = 0;

        this.vSpeed = 0;
        this.aSpeed = 0;

        this.bullet.image = img

        //os.add_ENTERFRAME(this.update, this);
        this.once(GameSprite.ON_DISPOSE, this, () => {
            os.remove_ENTERFRAME(this.update, this);
        });

    }

    /**
     * 向后弹开
     */
    bounce() {
        this.state = W26_CzBullet.STATE_DOUNCE;
        this.speed = 60;
    }


    fire() {
        this.speed = -100;
        this.state = W26_CzBullet.STATE_FIRE;
    }

    update() {
        if (this.state == W26_CzBullet.STATE_FIRE) {

        }
        else if (this.state == W26_CzBullet.STATE_INSERT) {
            var c = this.circleParent.circleRoot;
            var a = this.angle + 270;
            var rotaAngle = c.rotation - a;//圆圈的旋转角
            var r = this.circleParent.r;//半径
            r -= this.depth;
            r += this.bullet.height / 2;
            var radian = this.angleToRadian(rotaAngle);
            var x = c.x + Math.cos(radian) * r;
            var y = c.y + Math.sin(radian) * r;

            this.x = x;
            this.y = y;

            this.bullet.rotation = rotaAngle - 90;

        }
        else if (this.state == W26_CzBullet.STATE_DOUNCE) {

        }
        else if (this.state == W26_CzBullet.STATE_DROP) {
            this.speed += this.g / 60;
            if (this.speed > 60) {
                this.speed = 60;
            }
        }

        this.y += this.speed;
        this.x += this.vSpeed;
        this.bullet.rotation += this.aSpeed;
        this.bullet.rotation += 360;
        this.bullet.rotation %= 360;


    }

    insert() {
        this.speed = 0;
        this.state = W26_CzBullet.STATE_INSERT
    }

    drop() {
        this.state = W26_CzBullet.STATE_DROP;
        var sp = Math.floor(Math.random() * 5);
        this.speed = -30 + sp;//给个上升速度

        this.vSpeed = Math.floor(Math.random() * 10 - 5);//给个横向得力

        this.aSpeed = Math.floor(Math.random() * 10 - 5);

        //给个旋转得力
    }

    radianToAngle(radian) {
        return radian * 180 / Math.PI;
    }

    angleToRadian(angle) {
        return angle * Math.PI / 180;
    }
}

class W26_CzCircle extends GUI_15004 {
    static STATE_DEFAULT = 0;
    static STATE_BROKEN = 1;

    static QUAKE_SPEED = 2;
    static QUAKE_Y = 8;
    static ROTAION_SPEED_ARRAY = [-0.1, -0.05, -0.01, 0.01, 0.05, 0.1];//变速数组
    //static ROTAION_SPEED_ARRAY = [0.01];//变速数组
    changeSpeed: number;//变速频率
    nowSpeed: number;//当前速度
    isQuake: boolean;//是否震动
    isup: boolean;//是否向上震动
    oldy: number;//记录原始y
    stop: boolean;
    r: number;

    state: number;

    bullets: W26_CzBullet[];//插在上面得子弹

    currentTime: number;

    brokenC: {
        g1: number;
        g2: number;
        sp1: number;
        sp2: number;
        vsp1: number;
        vsp2: number;
        asp1: number;
        asp2: number;
    }

    /**
     * 构造函数
     */
    constructor(changeSpeed: number, r: number) {
        super();
        this.changeSpeed = changeSpeed;
        this.nowSpeed = W26_CzCircle.ROTAION_SPEED_ARRAY[0];
        //this.changeSpeedF();
        this.brokenC = {} as any;

        this.brokenC.g1 = 60;
        this.brokenC.g2 = 60;

        this.bullets = [];
        this.stop = false;
        //os.add_ENTERFRAME(this.update, this);
        this.once(GameSprite.ON_DISPOSE, this, () => {
            os.remove_ENTERFRAME(this.update, this);
            for (var i = 0; i < this.bullets.length; i++) {
                var b = this.bullets[i];
                if (b) {
                    b.dispose();
                }
            }
            this.bullets.length = 0;
        });

        this.broken1.visible = false;
        this.broken2.visible = false;
        this.r = r == 0 ? Math.floor(this.circleRoot.width / 2) : r;
        this.state = W26_CzCircle.STATE_DEFAULT;
    }

    update() {
        if (this.stop) return;
        if (this.state == W26_CzCircle.STATE_DEFAULT) {
            this.circleRoot.rotation += this.radianToAngle(this.nowSpeed);
            this.circleRoot.rotation += 360;
            this.circleRoot.rotation %= 360;
            /*
            for (var i = 0; i < this.bullets.length; i++) {
                this.bullets[i].update();
            }*/

            if (this.isQuake) {
                if (this.isup) {
                    this.circleRoot.y = this.circleRoot.y - W26_CzCircle.QUAKE_SPEED;
                    if (this.oldy - this.circleRoot.y >= W26_CzCircle.QUAKE_Y) {
                        this.isup = false;
                    }
                } else {
                    this.circleRoot.y = this.circleRoot.y + W26_CzCircle.QUAKE_SPEED;
                    if (this.oldy <= this.circleRoot.y) {
                        this.circleRoot.y = this.oldy;
                        this.isQuake = false;
                        this.isup = true;
                        this.oldy = null;
                    }
                }
            }

            var t = new Date().getTime();
            if (this.currentTime == null) {
                this.currentTime = t;
            }
            if (t - this.currentTime > this.changeSpeed * 1000) {
                this.currentTime = t;
                var randomNum = Math.floor(Math.random() * W26_CzCircle.ROTAION_SPEED_ARRAY.length);//随机获取变速数组中得一个速度
                this.nowSpeed = W26_CzCircle.ROTAION_SPEED_ARRAY[randomNum];
            }
        }
        else if (this.state == W26_CzCircle.STATE_BROKEN) {

            this.brokenC.sp1 += this.brokenC.g1 / 60;
            if (this.brokenC.sp1 > 60) {
                this.brokenC.sp1 = 60;
            }

            this.brokenC.sp2 += this.brokenC.g2 / 60;
            if (this.brokenC.sp2 > 60) {
                this.brokenC.sp2 = 60;
            }

            this.broken1.y += this.brokenC.sp1;
            this.broken1.x += this.brokenC.vsp1;
            this.broken1.rotation += this.brokenC.asp1;
            this.broken1.rotation += 360;
            this.broken1.rotation %= 360;

            this.broken2.y += this.brokenC.sp2;
            this.broken2.x += this.brokenC.vsp2;
            this.broken2.rotation += this.brokenC.asp2;
            this.broken2.rotation += 360;
            this.broken2.rotation %= 360;
        }
    }

    broken() {

        this.broken1.width = this.broken1.texture.width;
        this.broken2.width = this.broken2.texture.width;

        this.broken1.height = this.broken1.texture.height;
        this.broken2.height = this.broken2.texture.height;


        this.state = W26_CzCircle.STATE_BROKEN;
        this.circleRoot.visible = false;
        this.broken1.visible = true;
        this.broken2.visible = true;
        this.broken1.removeSelf();
        this.broken2.removeSelf();
        this.addChildAt(this.broken1, 0);
        this.addChildAt(this.broken2, 0);

        var sp = Math.floor(Math.random() * 5);
        this.brokenC.sp1 = -30 + sp;//给个上升速度
        sp = Math.floor(Math.random() * 5);
        this.brokenC.sp2 = -30 + sp;//给个上升速度

        this.brokenC.vsp1 = Math.floor(Math.random() * 20 - 10);//给个横向得力
        this.brokenC.vsp2 = Math.floor(Math.random() * 20 - 10);//给个横向得力

        this.brokenC.asp1 = Math.floor(Math.random() * 20 - 10);//给个横向得力
        this.brokenC.asp2 = Math.floor(Math.random() * 20 - 10);//给个横向得力


    }

    shake() {
        this.oldy = this.circleRoot.y;
        this.isQuake = true;
        this.isup = true;
    }

    moveBulletIn(bullet: W26_CzBullet) {
        var globalP = (bullet.parent as UIRoot).localToGlobal(new Point(bullet.x, bullet.y));
        bullet.removeSelf();
        this.addChildAt(bullet, 0);
        var localP = this.globalToLocal(globalP);
        bullet.x = localP.x;
        bullet.y = localP.y;
        bullet.angle = this.circleRoot.rotation;//记录当前角度
        bullet.circleParent = this;
        bullet.insert();
        this.bullets.push(bullet);
    }

    moveBulletOut(): W26_CzBullet[] {
        var bullets = [];
        var len = this.bullets.length;
        for (var i = 0; i < len; i++) {
            var b = this.bullets[i];
            b.removeSelf();
            bullets.push(b);
        }
        this.bullets.length = 0;
        return bullets;
    }

    changeSpeedF() {
        Callback.New(() => {
            var randomNum = Math.floor(Math.random() * W26_CzCircle.ROTAION_SPEED_ARRAY.length);//随机获取变速数组中得一个速度
            this.nowSpeed = W26_CzCircle.ROTAION_SPEED_ARRAY[randomNum];
            this.changeSpeedF();
        }, this).delayRunConver(this.changeSpeed * 1000, setTimeout);
    }

    radianToAngle(radian) {
        return radian * 180 / Math.PI;
    }

    angleToRadian(angle) {
        return angle * Math.PI / 180;
    }
}


class W26_Cz extends GUI_15001 {
    static GAME_COMPLETED = "GAME_COMPLETED";

    static PLUGIN_GUI_CZ = 15001;
    static PLUGIN_MODULE_TYPE_LEVEL = 1;

    isDebug: boolean;

    depth: number;//插入深度
    stopControl: boolean;//停止控制


    currentBullet: W26_CzBullet;//当前子弹
    fireBullet: W26_CzBullet;//发射子弹

    bullets: W26_CzBullet[];//所有子弹

    currentCircle: W26_CzCircle;//目标圆圈

    level: number;
    levels: number[];


    currentTime: number;
    targetTime: number;

    timestamp: number;

    keepTIme: boolean;

    boxMagazine: {//弹匣
        num: number,//总数
        useNum: number,//使用得数量
    }

    /**
     * 构造函数
     */
    constructor() {
        super();
        this.visible = false;
        this.bullets = [];
        this.boxMagazine = {} as any;
        this.depth = 10;
        //this.isDebug = true; 取消注释则是看到碰撞框
        this.level = 0;

        this.once(GameSprite.ON_DISPOSE, this, () => {
            stage.off(EventObject.MOUSE_DOWN, this, this.fire);
            os.remove_ENTERFRAME(this.update, this);
        })

        this.failButtons.visible = false;
    }


    changeLevel(level: number) {

        if (level > this.levels.length) {//最大关卡限制
            return;
        }

        this.level = level;

        var currentLevel = GameData.getModuleData(W26_Cz.PLUGIN_MODULE_TYPE_LEVEL, this.levels[level - 1]) as Module_W26_level;
        this.changeBoxMagazine(0, 0);
        this.changeBoxMagazine(0, currentLevel.num);

        this.targetTime = currentLevel.time;
        this.currentTime = this.targetTime;
        this.timestamp = new Date().getTime();

        this.timeLabel.text = this.currentTime.toString();

        this.currentBullet = null;
        this.fireBullet = null;

        for (var i = 0; i < this.bullets.length; i++) {
            if (this.bullets[i]) {
                this.bullets[i].removeSelf();
                this.bullets[i].dispose();
            }
        }

        this.bullets.length = 0;


        if (this.currentCircle) {
            this.currentCircle.removeSelf();
            this.currentCircle.dispose();
            this.currentCircle = null;
        }
        this.loadBullet();//装载一颗弹药，
        this.createCircle(currentLevel.circle, currentLevel.circle2, currentLevel.circle3, currentLevel.changeFrequency, currentLevel.r);//创建一个圆圈
        //
        this.stopControl = true;

        //显示关卡图
        this.levelImage.alpha = 1;
        this.levelImage.visible = true;
        this.levelImage.image = currentLevel.levelImage;
        if (!this.visible) {
            if (this.levelImage.texture) {
                this.visible = true;
            }
            else {
                this.levelImage.once(EventObject.LOADED, this, () => {
                    this.visible = true;
                });
            }
        }

        this.keepTIme = false;
        Tween.to(this.levelImage, { "alpha": 0 }, 1000, Ease.linearIn, Callback.New(() => {
            this.keepTIme = true;
            this.levelImage.visible = false;
            this.levelImage.alpha = 1;
            this.stopControl = false;
        }, this), 1300);


    }

    start(levels: number[]) {
        this.levels = levels;
        os.add_ENTERFRAME(this.update, this);
        stage.on(EventObject.MOUSE_DOWN, this, this.fire);
        if (levels.length == 0) {
            this.dispose();
        }
        this.changeLevel(1);
    }

    createCircle(p1: string, p2: string, p3: string, changeFrequency: number, r: number) {
        var circle = new W26_CzCircle(changeFrequency, r);

        circle.circleRoot.image = p1;
        circle.broken1.image = p2;
        circle.broken2.image = p3;

        circle.x = this.circleRoot.x + this.circleRoot.width / 2;
        circle.y = this.circleRoot.y + this.circleRoot.height / 2;
        this.mainStage.addChildAt(circle, 0);
        this.currentCircle = circle
        circle.oldy = circle.y;
    }

    /**
     * 改变速度
     */


    update() {

        if (this.currentCircle)
            this.currentCircle.update();

        for (var i = 0; i < this.bullets.length; i++) {
            if (this.bullets[i]) {
                this.bullets[i].update();

                if (this.bullets[i].y > stage.height + 20) {
                    this.bullets[i].removeSelf();
                    this.bullets[i].dispose();
                    this.bullets[i] = null;
                }


            }
        }


        var g = this.debugBackground.graphics;
        g.clear();

        if (this.fireBullet != null) {
            //碰撞检测，判断发射得是否和子弹碰撞

            var collisionResult = false;

            var gp = (this.fireBullet.parent as UIBase).localToGlobal(new Point(this.fireBullet.x, this.fireBullet.y));

            var rect1 = {
                x: gp.x - this.fireBullet.bullet.width / 2,
                y: gp.y - this.fireBullet.bullet.height / 2,
                width: this.fireBullet.bullet.width,
                height: this.fireBullet.bullet.height,
                angle: this.fireBullet.bullet.rotation,
                centerP: new Point(gp.x, gp.y)
            };


            for (var i = 0; i < this.currentCircle.bullets.length; i++) {
                var b = this.currentCircle.bullets[i];
                var gp = (b.parent as UIBase).localToGlobal(new Point(b.x, b.y));

                var rect2 = {
                    x: gp.x - b.bullet.width / 2,
                    y: gp.y - b.bullet.height / 2,
                    width: b.bullet.width,
                    height: b.bullet.height,
                    angle: b.bullet.rotation,
                    centerP: new Point(gp.x, gp.y)
                };


                if (W26_CzOBB.collision(rect1, rect2)) {
                    // trace("撞到了,寄")
                    collisionResult = true;
                }
                //var rect1 = {x:bullet}

            }

            //没撞到子弹上，检测撞到圆圈上
            if (!collisionResult) {
                var r = this.currentCircle.r;//半径
                //trace(r)
                var z = this.fireBullet.bullet.height / 2;//偏移
                if (this.fireBullet.y - z <= this.currentCircle.y + r - this.fireBullet.depth) {
                    this.fireBullet.y = this.currentCircle.y + r + z - this.fireBullet.depth;
                    this.currentCircle.moveBulletIn(this.fireBullet);//把子弹移动到圆圈对象里由圆圈对象管理
                    this.fireBullet = null;
                    this.shakeCircleRoot();
                    this.onComplete(true);
                }
                GameAudio.playSE("asset/audio/se/Jump_woodFloor.ogg", 0.2);
            }
            else {//撞到子弹上

                this.onComplete(false);
                this.fireBullet = null;
            }
        }

        //倒计时更新
        if (this.keepTIme) {
            var now = new Date().getTime();
            if (now - this.timestamp > 1000) {
                this.timestamp = now;
                this.currentTime -= 1;
                if (this.currentTime < 0) {
                    this.currentTime = 0;
                    this.onComplete(false);
                }
                this.timeLabel.text = this.currentTime.toString();
            }
        }
        if (this.isDebug)
            this.debugDrawRect();


    }

    /**
     * 插入后震动一下，向上震动
     */
    shakeCircleRoot() {
        this.currentCircle.shake();
    }

    /**
     * 装载子弹
     */
    loadBullet() {
        var currentLevel = GameData.getModuleData(W26_Cz.PLUGIN_MODULE_TYPE_LEVEL, this.levels[this.level - 1]) as Module_W26_level;
        var centerX = this.circleRoot.x + this.circleRoot.width / 2;;
        var centerY = this.bulletPosY.y + this.bulletPosY.height / 2;
        var bullet = new W26_CzBullet(currentLevel.bullet);
        this.readyBullet.addChild(bullet);
        bullet.x = centerX;
        bullet.y = centerY;

        this.currentBullet = bullet;

        this.bullets.push(this.currentBullet);
    }

    changeBoxMagazineUseNum(value) {
        var use = this.boxMagazine.useNum + value;
        this.changeBoxMagazine(use, this.boxMagazine.num);
    }

    changeBoxMagazineNum(value) {
        var num = this.boxMagazine.num + value;
        this.changeBoxMagazine(this.boxMagazine.useNum, num);
    }

    changeBoxMagazine(use: number, num: number) {
        if (num != this.boxMagazine.num) {
            this.magazine.removeChildren();
            var currentLevel = GameData.getModuleData(W26_Cz.PLUGIN_MODULE_TYPE_LEVEL, this.levels[this.level - 1]) as Module_W26_level;
            for (var i = 0; i < num; i++) {
                var magazineBullet = new W26_CzMagazineBullet(currentLevel.bullet2, currentLevel.bullet1);
                var h = magazineBullet.full.height;
                this.magazine.addChild(magazineBullet);
                magazineBullet.y += this.magazine.height;//移动到左下角
                magazineBullet.y -= (5 + h) * i;//依次向上
            }
        }
        this.boxMagazine.num = num;
        this.boxMagazine.useNum = use;

        for (var i = 0; i < num; i++) {
            var magazineBullet = this.magazine.getChildAt(i) as W26_CzMagazineBullet;
            magazineBullet.fullBullet();
        }
        for (var i = 0; i < use; i++) {
            var magazineBullet = this.magazine.getChildAt(this.magazine.numChildren - 1 - i) as W26_CzMagazineBullet;
            magazineBullet.useBullet();
        }
    }

    /**
     * 发射子弹
     */
    fire() {
        if (this.stopControl) return;
        if (this.boxMagazine.useNum < this.boxMagazine.num) {
            this.stopControl = true;
            this.fireBullet = this.currentBullet;
            this.currentBullet.fire();
            this.currentBullet = null;
            this.changeBoxMagazineUseNum(1);//取出一个子弹

        }
    }

    /**
     * 发射完成后
     */
    onComplete(result: boolean) {

        if (result) {
            if (this.boxMagazine.useNum < this.boxMagazine.num) {
                this.loadBullet();
                this.stopControl = false;
            }
            else {//过关
                this.keepTIme = false;
                var bullet = this.currentCircle.bullets;
                for (var i = 0; i < bullet.length; i++) {
                    bullet[i].drop();
                }
                this.currentCircle.bullets.length = 0;

                this.currentCircle.broken();

                if (this.level == this.levels.length) {
                    EventUtils.happen(W26_Cz, W26_Cz.GAME_COMPLETED, [true]);
                    Tween.to(this, { "alpha": 0 }, 1000, Ease.linearIn, Callback.New(() => {
                        GameUI.dispose(W26_Cz.PLUGIN_GUI_CZ);
                    }, this));
                }
                else {
                    Callback.New(() => {
                        this.changeLevel(this.level + 1);
                    }, this).delayRun(1500, setTimeout);
                }
                //this.changeLevel(this.level + 1);
            }
        }
        else {//失败
            this.keepTIme = false;
            if (this.fireBullet) {
                this.fireBullet.bounce();
            }
            if (this.currentCircle) {
                this.currentCircle.stop = true;
            }

            this.failButtons.visible = true;

            this.quitButton.offAll();

            this.quitButton.once(EventObject.CLICK, this, () => {
                this.failButtons.visible = false;
                EventUtils.happen(W26_Cz, W26_Cz.GAME_COMPLETED, [false]);
                Tween.to(this, { "alpha": 0 }, 1000, Ease.linearIn, Callback.New(() => {

                    GameUI.dispose(W26_Cz.PLUGIN_GUI_CZ);
                }, this));
            });

            this.restartButton.offAll();

            this.restartButton.once(EventObject.CLICK, this, () => {
                this.failButtons.visible = false;
                this.changeLevel(1);
            });
        }
    }

    /**
     * 绘制rect碰撞体图形
     */
    debugDrawRect() {

        if (!this.currentCircle) return;
        var bullets = this.currentCircle.bullets;
        var g = this.debugBackground.graphics;
        g.clear();

        for (var i = 0; i < bullets.length; i++) {
            var b = bullets[i];
            var gp = (b.parent as UIBase).localToGlobal(new Point(b.x, b.y));

            var rect = { x: gp.x - b.bullet.width / 2, y: gp.y - b.bullet.height / 2, width: b.bullet.width, height: b.bullet.height, angle: b.bullet.rotation, centerP: new Point(gp.x, gp.y) };
            var points = W26_CzOBB.getRotatePoints2(rect);
            g.drawLine(points[0].x, points[0].y, points[1].x, points[1].y, "#FFFFFF", 3);
            g.drawLine(points[1].x, points[1].y, points[2].x, points[2].y, "#FFFFFF", 3);
            g.drawLine(points[2].x, points[2].y, points[3].x, points[3].y, "#FFFFFF", 3);
            g.drawLine(points[3].x, points[3].y, points[0].x, points[0].y, "#FFFFFF", 3);
            g.drawRect(gp.x, gp.y, 10, 10, "#08FFFF", "#FFFFFF", 4);
        }

        if (this.fireBullet) {
            var gp = (this.fireBullet.parent as UIBase).localToGlobal(new Point(this.fireBullet.x, this.fireBullet.y));

            var rect = {
                x: gp.x - this.fireBullet.bullet.width / 2,
                y: gp.y - this.fireBullet.bullet.height / 2,
                width: this.fireBullet.bullet.width,
                height: this.fireBullet.bullet.height,
                angle: this.fireBullet.bullet.rotation,
                centerP: new Point(gp.x, gp.y)
            };
            var points = W26_CzOBB.getRotatePoints2(rect);
            g.drawLine(points[0].x, points[0].y, points[1].x, points[1].y, "#FFFFFF", 3);
            g.drawLine(points[1].x, points[1].y, points[2].x, points[2].y, "#FFFFFF", 3);
            g.drawLine(points[2].x, points[2].y, points[3].x, points[3].y, "#FFFFFF", 3);
            g.drawLine(points[3].x, points[3].y, points[0].x, points[0].y, "#FFFFFF", 3);
        }


        if (this.currentBullet) {
            var gp = (this.currentBullet.parent as UIBase).localToGlobal(new Point(this.currentBullet.x, this.currentBullet.y));

            var rect = {
                x: gp.x - this.currentBullet.bullet.width / 2,
                y: gp.y - this.currentBullet.bullet.height / 2,
                width: this.currentBullet.bullet.width,
                height: this.currentBullet.bullet.height,
                angle: this.currentBullet.bullet.rotation,
                centerP: new Point(gp.x, gp.y)
            };
            var points = W26_CzOBB.getRotatePoints2(rect);
            g.drawLine(points[0].x, points[0].y, points[1].x, points[1].y, "#FFFFFF", 3);
            g.drawLine(points[1].x, points[1].y, points[2].x, points[2].y, "#FFFFFF", 3);
            g.drawLine(points[2].x, points[2].y, points[3].x, points[3].y, "#FFFFFF", 3);
            g.drawLine(points[3].x, points[3].y, points[0].x, points[0].y, "#FFFFFF", 3);
        }

    }

    radianToAngle(radian) {
        return radian * 180 / Math.PI;
    }

    angleToRadian(angle) {
        return angle * Math.PI / 180;
    }
}

class W26_CzProjection {
    min: number;
    max: number;
    constructor(min, max) {
        this.min = min;
        this.max = max;
    }

    overlaps(projection: W26_CzProjection): boolean {
        return this.max > projection.min && projection.max > this.min;
    }
}

class W26_CzOBB {
    constructor() {

    }

    /**
     * 得到旋转后精灵左上角坐标
     * @param sp 
     * @return [Point] 
     */
    static getRotatePoint(sp: GameSprite): Point {
        var lp = (sp.parent as GameSprite).localToGlobal(new Point(sp.x, sp.y));//全局坐标
        var getRotatePoint = new Point(lp.x + sp.width / 2, lp.y + sp.height / 2);
        var newRotate = sp.rotation;//旋转角
        var rotatePoint = new Point(
            (sp.x - getRotatePoint.x) * Math.cos(newRotate / 180 * Math.PI) - (sp.y - getRotatePoint.y) * Math.sin(newRotate / 180 * Math.PI) + getRotatePoint.x,
            (sp.x - getRotatePoint.x) * Math.sin(newRotate / 180 * Math.PI) + (sp.y - getRotatePoint.y) * Math.cos(newRotate / 180 * Math.PI) + getRotatePoint.y
        );
        return rotatePoint;
    }

    static getRotatePoint2(p1: Point, p2: Point, angle: number): Point {
        var getRotatePoint = p1;
        var newRotate = ((angle % 360) + 360) % 360;
        var rotatePoint = new Point(
            (p2.x - getRotatePoint.x) * Math.cos(newRotate / 180 * Math.PI) - (p2.y - getRotatePoint.y) * Math.sin(newRotate / 180 * Math.PI) + getRotatePoint.x,
            (p2.x - getRotatePoint.x) * Math.sin(newRotate / 180 * Math.PI) + (p2.y - getRotatePoint.y) * Math.cos(newRotate / 180 * Math.PI) + getRotatePoint.y
        );
        return rotatePoint;
    }

    //极坐标位移
    static polarCoordinates(point: Point, angle: number, distance: number): Point {
        angle = (angle % 360 + 360) % 360;
        var p2 = new Point();
        if (angle > 0 && angle < 90) {
            p2.x = point.x + Math.cos(angle * 2 * Math.PI / 360) * distance;
            p2.y = point.y + Math.sin(angle * 2 * Math.PI / 360) * distance;
        } else if (angle > 90 && angle < 180) {
            p2.x = point.x - Math.sin((angle - 90) * 2 * Math.PI / 360) * distance;
            p2.y = point.y + Math.cos((angle - 90) * 2 * Math.PI / 360) * distance;
        } else if (angle > 180 && angle < 270) {
            p2.x = point.x - Math.cos((angle - 180) * 2 * Math.PI / 360) * distance;
            p2.y = point.y - Math.sin((angle - 180) * 2 * Math.PI / 360) * distance;
        } else if (angle > 270 && angle < 360) {
            p2.x = point.x + Math.sin((angle - 270) * 2 * Math.PI / 360) * distance;
            p2.y = point.y - Math.cos((angle - 270) * 2 * Math.PI / 360) * distance;
        }
        if (angle == 0 || angle == 360) {
            p2.x = point.x + distance;
            p2.y = point.y;
        } else if (angle == 90) {
            p2.x = point.x;
            p2.y = point.y + distance;
        } else if (angle == 180) {
            p2.x = point.x - distance;
            p2.y = point.y;
        } else if (angle == 270) {
            p2.x = point.x;
            p2.y = point.y - distance;
        }
        return p2;
    };

    static getRotatePoints(sp): Point[] {
        var arr = [];
        arr.push(this.getRotatePoint(sp));
        arr.push(this.polarCoordinates(arr[0], sp.angle, sp.width));
        arr.push(this.polarCoordinates(arr[1], sp.angle + 90, sp.height));
        arr.push(this.polarCoordinates(arr[0], sp.angle + 90, sp.height));
        return arr;
    };

    static getRotatePoints2(sp: { x: number, y: number, width: number, height: number, angle: number, centerP: Point }): Point[] {
        var arr = [];
        var centerP = sp.centerP;
        var p2 = new Point(sp.x, sp.y);
        arr.push(this.getRotatePoint2(centerP, p2, sp.angle));
        arr.push(this.polarCoordinates(arr[0], sp.angle, sp.width));
        arr.push(this.polarCoordinates(arr[1], sp.angle + 90, sp.height));
        arr.push(this.polarCoordinates(arr[0], sp.angle + 90, sp.height));
        return arr;
    }

    static pointToVec(vecs) {
        var returnArr = [];
        var len = vecs.length - 1;
        for (var i = 0; i < len; i++) {
            var v1 = new W26_CzVector(vecs[i]);
            var v2 = new W26_CzVector(vecs[i + 1]);
            returnArr.push(v1.edge(v2).normalize());
        }
        var v1 = new W26_CzVector(vecs[vecs.length - 1]);
        var v2 = new W26_CzVector(vecs[0]);
        returnArr.push(v1.edge(v2).normalize());
        return returnArr;
    }

    static getP(axis, points) {
        var scalars = [],
            v = new W26_CzVector();
        points.forEach(function (point) {
            v.x = point.x;
            v.y = point.y;
            scalars.push(v.dotProduct(axis))
        });

        return new W26_CzProjection(Math.min.apply(Math, scalars),
            Math.max.apply(Math, scalars))
    }

    /**
     * 碰撞
     */
    static collision(rect: { x: number, y: number, width: number, height: number, angle: number, centerP: Point },
        rect2: { x: number, y: number, width: number, height: number, angle: number, centerP: Point }): boolean {
        var pointArr1 = this.getRotatePoints2(rect);
        var pointArr2 = this.getRotatePoints2(rect2);
        var vec1 = this.pointToVec(pointArr1);
        var vec2 = this.pointToVec(pointArr2);
        var allVec = vec1.concat(vec2);
        var len = allVec.length - 1;
        //trace(allVec);
        for (var i = 0; i < len; i++) {
            var axis = allVec[i];
            var p1 = this.getP(axis, pointArr1);
            var p2 = this.getP(axis, pointArr2);
            if (!p1.overlaps(p2)) {
                return false;
            }
        }
        return true;
    }
}

class W26_CzVector {
    x: number;
    y: number;
    constructor(p: Point = undefined) {
        if (p == undefined) {
            this.x = 0;
            this.y = 0;
        }
        else {
            this.x = p.x;
            this.y = p.y;
        }
    }

    getMagnitude() {
        return Math.sqrt(Math.pow(this.x, 2) + Math.pow(this.y, 2))
    }

    add(vector: W26_CzVector) {
        var v = new W26_CzVector();
        v.x = this.x + vector.x;
        v.y = this.y + vector.y;
        return v
    }

    subtract(vector: W26_CzVector) {
        var v = new W26_CzVector();
        v.x = this.x - vector.x;
        v.y = this.y - vector.y;
        return v
    }

    dotProduct(vector: W26_CzVector) {
        return this.x * vector.x + this.y * vector.y
    }

    // 由两点生成边
    edge(vector: W26_CzVector) {
        return this.subtract(vector)
    }

    // 垂直，即投影轴
    perpendicular() {
        var v = new W26_CzVector();
        v.x = this.y;
        v.y = 0 - this.x;
        return v
    }

    normalize() {
        var v = new W26_CzVector(),
            m = this.getMagnitude();

        if (m !== 0) {
            v.x = this.x / m;
            v.y = this.y / m;
        }
        return v
    }

    // 投影轴的单位向量
    normal() {
        var p = this.perpendicular();
        return p.normalize();
    }

}



module CommandExecute {
    /**
     * 自定义命令执行 1表示对应1号命令
     * @param commandPage 事件页
     * @param cmd 当前的事件命令
     * @param trigger 触发器
     * @param triggerPlayer 触发器对应的玩家
     * @param playerInput 玩家输入值，用于暂停执行该触发器事件并等待玩家输入后获得的值，执行完该函数后会被清空
     * @param p 自定义命令参数 1表示对应1号命令的参数
     */
    export function customCommand_15001(commandPage: CommandPage, cmd: Command, trigger: CommandTrigger, triggerPlayer: ClientPlayer, playerInput: any[], p: CustomCommandParams_15001): void {

        var gui_cz = GameUI.show(W26_Cz.PLUGIN_GUI_CZ) as W26_Cz;
        trigger.pause = true;
        trigger.offset(1);

        EventUtils.addEventListenerFunction(W26_Cz, W26_Cz.GAME_COMPLETED, (result: boolean) => {
            //trace(result)
            EventUtils.removeEventListenerFunction(W26_Cz, W26_Cz.GAME_COMPLETED, arguments.callee, this);
            Game.player.variable.setSwitch(p.result, result ? 1 : 0);
            //trace(Game.player.variable.getSwitch(p.result));
        }, this);

        EventUtils.addEventListenerFunction(GameUI, GameUI.EVENT_CLOSE_SYSTEM_UI, (trigger: CommandTrigger, closeUIID: number) => {

            if (closeUIID == W26_Cz.PLUGIN_GUI_CZ) {
                //ArrayUtils.remove(isWaitingUICloseInfos, t);
                EventUtils.removeEventListenerFunction(GameUI, GameUI.EVENT_CLOSE_SYSTEM_UI, arguments.callee, this);
                CommandPage.executeEvent(trigger, []);
            }
        }, this, [trigger]);

        gui_cz.start(p.levels);
    }
}